/**
 * 记录界面状态
 *
 * 特殊功能：多个组件若读取同一个 key，一方进行更新时，也会触发另一个方的重新渲染
 */
import { tuple } from '@gnlab/utils'
import { MemSubject } from '@gnlab/utils/rx'
import { KVStorageManager } from '@/lib/storage'
import { useStreams } from '@/lib/utils'
import services from '@/services'

class UIMemory {
  private _storage: KVStorageManager<unknown> | null = null

  get storage() {
    if (this._storage === null) {
      // 第一次读取 storage 时才初始化
      this._storage = new KVStorageManager({
        topic: `ui-memory-${services.auth.account$.value?.id ?? ''}`,
        defaults: {},
      })
    }
    return this._storage
  }

  private readonly subjects = new Map<string, MemSubject<unknown>>()

  // 获取指定 key 的 subject，可用来取值、监听、赋值
  get<T>(key: string) {
    if (!this.subjects.has(key)) {
      const subject = new MemSubject(this.storage.get(key))
      this.subjects.set(key, subject)
      subject.subscribe(value => this.storage.set(key, value))
    }
    return this.subjects.get(key)! as MemSubject<T | undefined>
  }

  getValue<T>(key: string) {
    return this.get<T>(key).value
  }

  setValue<T>(key: string, value: T) {
    this.get<T>(key).next(value)
  }
}
const memory = new UIMemory()
export { memory as UIMemory }

function useUIMemory<T>(key: string, defaults: T): [T, (value: T) => void]
function useUIMemory<T>(key: string): [T | undefined, (value: T) => void]
function useUIMemory<T>(key: string, defaults?: T) {
  const [value] = useStreams(memory.get<T>(key))
  const setValue = useCallback((_value: T) => memory.setValue(key, _value), [key])
  return tuple(value ?? defaults, setValue)
}
export default useUIMemory
